package com.cosyhut.blocks.factory;

//import java.util.logging.Level;
//import com.jme.util.LoggingSystem;

import com.jme.scene.*;
import com.jme.scene.shape.*;
import com.jme.math.Vector3f;
import com.jme.scene.state.*;

import com.cosyhut.blocks.engine.*;
import com.cosyhut.blocks.display.*;
import com.cosyhut.blocks.jode.*;

import java.util.*;
import java.util.logging.Level;
import com.jme.util.LoggingSystem;

/**
 * 
 * @author TimWorks Jan 24, 2007
 * 
 * A BFactory contains all information about A Block or a BJoint. given a Block
 * ID or a BJoint ID it could create the Block or BJoint. it might need to load
 * all the data from an extern file (migth be XML format). Further more, it
 * could load BRobot data to compose a BRobot
 * 
 */
public class BFactory {
	private static BFactory instance = null;

	protected BFactory() {
	}

	public static BFactory get() {
		if (instance == null) {
			instance = new BFactory();
		}
		return instance;
	}

	boolean _init = false;

	private Engine _engine;
	private GRenderer _renderer;
	
	protected static float _unit = 0.001f;

	public static float units(int size) {
		return _unit * size;
	}
	
    public void init(Engine e, GRenderer r) {
    	this._engine = e;
    	this._renderer = r;
    	
    	this._geoms = new TreeMap<String, MGeom>();
    	MGeomLoader.load("", this);
    	this._joints = new TreeMap<String, MJoint>();
    	MJointLoader.load("", this);
    	this._blocks = new TreeMap<String, MBlock>();
    	MBlockLoader.load("", this);

    	this.createEnv();
    	this.createRobots();
    }
    
    private void createEnv() {
    	Node _env = new Node();
    	_env.setLocalTranslation(new Vector3f(0f, 0f, 0f));

        float size = 8;
        float height = 0;

        Box floor = new Box("floor", new Vector3f(0-size, height, 0-size), new Vector3f(size, height, size));
        
        // set floor to transparent
        AlphaState af = this._renderer.getRenderer().createAlphaState();
        af.setEnabled(true);
        af.setBlendEnabled(true);
        // Set the source function setting.
        af.setSrcFunction(AlphaState.SB_SRC_ALPHA);
        // Set the destination function setting.
        af.setDstFunction(AlphaState.SB_ONE_MINUS_SRC_ALPHA);
        // Enable the test.
        af.setTestEnabled(true);
        // Set the test function to TF_GREATER.
        af.setTestFunction(AlphaState.TF_GREATER);
        
        floor.setRenderState(af);
        floor.updateRenderState();
/*
        Disk floor = new Disk("floor", 10, 10, size);
        WireframeState wf = this._renderer.getRenderer().createWireframeState();
        wf.setEnabled(true);
        floor.setRenderState(wf);
        com.jme.math.Matrix3f rotation = new com.jme.math.Matrix3f();
        rotation.loadIdentity();
        rotation.fromAngleAxis((float)(Math.PI/2f), new Vector3f(1f, 0f, 0f));
        floor.setLocalRotation(rotation);
        floor.setLocalTranslation(new com.jme.math.Vector3f(0f, -2f, 0f));
*/        
        _env.attachChild(floor);
    	this._renderer.getRoot().attachChild(_env);
    	
    	//SWIGTYPE_p_dxGeom geomFloor = 
    		jode.dCreatePlane(this._engine.getEnvSpace(), 0f, 1f, 0f, 0f);
    }

    private void createRobots() {
        BRobot robot1 = new BRobotSimple("Simple_001", this._engine, this._renderer);
        this._renderer.addRobot(robot1);
        this._engine.addRobot(robot1);
    }
    
    // Geom --------------------------------------------------------------------
    private TreeMap<String, MGeom> _geoms;
	
    public void addGeomModel(MGeom model) {
    	this._geoms.put(model.getName(), model);
    }
    public ODEGeom createGeom(String name) {
    	MGeom model = (MGeom)this._geoms.get(name);
    	if (null == model) {
    		LoggingSystem.getLogger().log(Level.WARNING, "geom model '"+name+"' not found\n");
    		assert(false);
    	}
    	return new ODEGeom(model);
    }
    // Joint --------------------------------------------------------------------
    private TreeMap<String, MJoint> _joints;
	
    public void addJointModel(MJoint model) {
    	this._joints.put(model.getName(), model);
    }
    public ODEJoint createJoint(String name) {
    	MJoint model = (MJoint)this._joints.get(name);
    	if (null == model) {
    		LoggingSystem.getLogger().log(Level.WARNING, "joint model '"+name+"' not found\n");
    		assert(false);
    	}
    	return new ODEJoint(model);
    }
    public ODEJointPoint createJointPoint() {
    	return new ODEJointPoint();
    }
    // Block --------------------------------------------------------------------
    private TreeMap<String, MBlock> _blocks;
	
    public void addBlockModel(MBlock model) {
    	this._blocks.put(model.getName(), model);
    }
    public Block createBlock(String name) {
    	MBlock model = (MBlock)this._blocks.get(name);
    	if (null == model) {
    		LoggingSystem.getLogger().log(Level.WARNING, "block model '"+name+"' not found\n");
    		assert(false);
    	}
    	return new Block(model, this._engine, this._renderer);
    	
    }
    
}
